#include "../include/thread_pool.h"
#include "../include/func.h"

int printQueue(taskQueue_t *pQueue) {
    node_t *pCurr = pQueue->pFront;
    while (pCurr != NULL) {
        printf("%3d ", pCurr->netfd);
        pCurr = pCurr->pNext;
    }   
    printf("\n");
    return 0;                                                                                                         
}

void *threadFunc(void *arg) {
    threadPool_t *pThreadPool = (threadPool_t*)arg;
    while(1) {
        pthread_mutex_lock(&pThreadPool->mutex);
        while (pThreadPool->taskQueue.queueSize == 0 && pThreadPool->exitFlag == 0) {
            pthread_cond_wait(&pThreadPool->cond, &pThreadPool->mutex);
        }
        //检查退出状态
        if(pThreadPool->exitFlag == 1){
            //工人因为要退出而被唤醒
            printf("worker going to exit!\n");
            pthread_mutex_unlock(&pThreadPool->mutex);
            pthread_exit(NULL);
        }
        //队列非空
        int netfd = pThreadPool->taskQueue.pFront->netfd;
        deQueue(&pThreadPool->taskQueue);
        pthread_mutex_unlock(&pThreadPool->mutex);
        printf("thread netfd = %d\n", netfd);
        printf("new client is connecting...\n");
        // 连接日志
        int fd_log = open("../log/Netdisk.log", O_RDWR|O_CREAT|O_APPEND, 0666);
        RECORD_LOG_CONNECT(fd_log, netfd);
        close(fd_log);
        // 先进行用户登录
        login_server(netfd);
        printf("login success!\n");

        // 初始化用户目录栈
        dir_stack_t dstack;
        dir_stack_init(&dstack);

        int epfd = epoll_create(10);
        epollAdd(epfd, netfd);
        struct epoll_event readySet[8];
        int close_flag = 0; // 断开与客户端连接的标志
        while (1) {
            int readyNum = epoll_wait(epfd, readySet, 1, -1);
            for (int i = 0; i < readyNum; i++) {
                if (readySet[i].data.fd == netfd) {
                    int tag = 0; // 客户端命令类型tag
                    // 小火车初始化
                    train_t train;
                    memset(&train, 0, sizeof(train_t));
                    int ret = recv(netfd, &train.tag, sizeof(train.tag), MSG_WAITALL);
                    if (ret == 0) {
                        // 对面客户端已退出
                        close_flag = 1;
                        break;
                    }
                    tag = train.tag;
                    printf("---------------------------\n");
                    printf("tag = %d\n", tag);
                    // 客户端主动退出的信号
                    if (tag == -1) {
                        close_flag = 1;
                        break;
                    }

                    // 接收命令
                    recv(netfd, &train.data_length, sizeof(train.data_length), MSG_WAITALL);
                    recv(netfd, &train.data, train.data_length, MSG_WAITALL);
                    cmd_t cmd;
                    memset(&cmd, 0, sizeof(cmd_t));
                    memcpy(&cmd, &train.data, train.data_length);
                    // 打印客户端命令信息
                    printf("length = %d\n", train.data_length);
                    printf("argc = %d\n", cmd.argc);
                    for (int j = 0; j < cmd.argc; j++) {
                        printf("cmd argv %d = %s\n", j, cmd.cmd[j]);
                    }
                    // 日志记录
                    int fd_log = open("../log/Netdisk.log", O_RDWR|O_CREAT|O_APPEND, 0666);
                    RECORD_LOG_CMD(fd_log, netfd, &cmd);
                    close(fd_log);
                    // 判断tag获得命令类型
                    switch(tag) {
                    case TAGPWD:
                        do_pwd(netfd, &train, &dstack);
                        break;
                    case TAGLS:
                        do_ls(netfd, &train, &dstack);
                        break;
                    case TAGCD:
                        do_cd(netfd, &train, &cmd , &dstack);
                        break;
                    case TAGMKDIR:
                        do_mkdir(netfd, &train, &cmd, dstack);
                        break;
                    case TAGRMDIR:
                        do_rmdir(netfd, &train, &cmd, dstack);
                        break;
                    case TAGREMOVE:
                        do_rm(netfd, &train, &cmd, dstack);
                        break;
                    case TAGGETS:
                        do_gets(netfd, &train, &cmd, dstack);
                        break;
                    case TAGPUTS:
                        do_puts(netfd, &train, &cmd, dstack);
                        break;
                    default:
                        break;
                    }
                }
            }
            if (close_flag == 1) {
                printf("client already exit.\nsession finished.\n");
                /* printf("------------------------------------------\n"); */
                close(netfd);
                break;
            }
        }

    }
}

int makeWorker(threadPool_t *pThreadPool, int workernum) {
    pThreadPool->tidArr.workernum = workernum;
    for (int i = 0; i < workernum; i++) {
        pthread_t tid;
        pthread_create(&tid, NULL, threadFunc, pThreadPool);
        pThreadPool->tidArr.arr[i] = tid;
        printf("create tid %ld\n", tid);
    }
    return 0;
}
